// Special behaviours
//--------------------------------
#ifndef BSPECIAL_H
#define BSPECIAL_H
#include "behaviour.h"

// Called to find a light source's radius
// Param lightRange - return value
class BIPortal : public BIConst< Map**, uint*, uint*, uint* > {
public:

    enum PortalType {
        PORTAL_DOWN,
        PORTAL_UP,
        PORTAL_ANY
    };

    BEHAVIOUR_CALL const
    {
        return Portal( a0, a1, a2, a3 );
    }

    BEHAVIOUR_START
    {
        *a1 = 0;
        *a2 = 0;
        *a3 = 0;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Portal( Map** target, uint* x, uint* y, uint* type ) const = 0;

};

// Called to find a light source's radius
// Param lightRange - return value
class BILight : public BIConst< int* > {
public:

    enum StandardLightRadii {
        SMALL_FIRE_RADIUS = 3,
        MED_FIRE_RADIUS = 5,
        BIG_FIRE_RADIUS = 8,
        SMALL_SMOULDER_RADIUS = 1,
        MED_SMOULDER_RADIUS = 2,
        BIG_SMOULDER_RADIUS = 3
    };

    BEHAVIOUR_CALL const
    {
        return Light( a0 );
    }

    BEHAVIOUR_START
    {
        *a0 = 0;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Light( int* lightRange ) const = 0;

};

// Called to find status texts
enum StatusType {
    STATUS_GOOD,
    STATUS_BAD,
    STATUS_NEUTRAL
};
typedef std::pair< std::string, uint > StatusEffect;
typedef std::vector< StatusEffect > StatusEffectList;
class BIStatusEffects : public BIConst< StatusEffectList* > {
public:

    BEHAVIOUR_CALL const
    {
        return StatusEffects( a0 );
    }

    BEHAVIOUR_START
    {
        a0->clear();
    }
    BEHAVIOUR_END { }

protected:

    virtual bool StatusEffects( StatusEffectList* list ) const = 0;

};

// Called to find a player-specific stats ~ unused so far
// Param hunger     - returns hunger level
// Param corruption - returns corruption level
class BIHeroStats : public BIConst< int*, int* > {
public:

    BEHAVIOUR_CALL const
    {
        return HeroStats( a0, a1 );
    }

    BEHAVIOUR_START
    {
        *a0 = 0;
        *a1 = 0;
    }

    BEHAVIOUR_END
    {
        *a0 = std::max( 0, *a0 );
        *a1 = std::max( 0, *a1 );
    }

protected:

    virtual bool HeroStats( int* hunger, int* corruption ) const = 0;

};

// Called to modify player-specific stats ~ unused so far
// Param hunger     - value to add to hunger level
// Param corruption - value to add to corruption level
class BIOnModHeroStats : public BI< int*, int* > {
public:

    BEHAVIOUR_CALL
    {
        return OnModHeroStats( a0, a1 );
    }

    BEHAVIOUR_START { }
    BEHAVIOUR_END { }

protected:

    virtual bool OnModHeroStats( int* hungerMod, int* corruptionMod ) const = 0;

};

// Called to find out if something is on fire ~ unused; remove?
// Param fireType - fire type return
class BIFire : public BIConst< uint* > {
public:

    enum FireType {
        FIRE_NOT         = 0,
        FIRE_ON_FIRE     = 1,
        FIRE_SMOULDERING = 2,
        FIRE_CHARRED     = 4
    };

    BEHAVIOUR_CALL const
    {
        return Fire( a0 );
    }

    BEHAVIOUR_START
    {
        *a0 = FIRE_NOT;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Fire( uint* fireType ) const = 0;

};

class BIFlammable : public BIConst< uint* > {
public:

    enum FlammableType {
        FLAMMABLE_NOT              = 0,
        FLAMMABLE_BURN_INDEFINITE  = 1,
        FLAMMABLE_BURN_EXTRA_LONG  = 2,
        FLAMMABLE_BURN_LONG        = 4,
        FLAMMABLE_BURN_SHORT       = 8,
        FLAMMABLE_BURN_EXTRA_SHORT = 16,
        FLAMMABLE_BURN             = FLAMMABLE_BURN_INDEFINITE | FLAMMABLE_BURN_EXTRA_LONG | FLAMMABLE_BURN_LONG |
                                     FLAMMABLE_BURN_SHORT      | FLAMMABLE_BURN_EXTRA_SHORT,
        FLAMMABLE_SMOULDER_LONG    = 32,
        FLAMMABLE_SMOULDER_SHORT   = 64,
        FLAMMABLE_SMOULDER         = FLAMMABLE_SMOULDER_LONG | FLAMMABLE_SMOULDER_SHORT,
        FLAMMABLE_DESTROY          = 128,
        FLAMMABLE_CHAR             = 256,
        FLAMMABLE_BURN_BRIGHT      = 512,
        FIRE_SOURCE_LIMITED        = 1024,
        FIRE_SOURCE_UNLIMITED      = 2048,
        FIRE_SOURCE                = FIRE_SOURCE_LIMITED | FIRE_SOURCE_UNLIMITED
    };

#define EXTRA_LONG_DICE  25, 250, 100
#define LONG_DICE        15, 100,  50
#define SHORT_DICE       10,  50,  20
#define EXTRA_SHORT_DICE  5,  10,  10

    BEHAVIOUR_CALL const
    {
        return Flammable( a0 );
    }

    BEHAVIOUR_START
    {
        *a0 = FLAMMABLE_NOT;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Flammable( uint* flammableType ) const = 0;

};

class BIOnSetFire : public BI<> {
public:

    BEHAVIOUR_CALL
    {
        return OnSetFire();
    }

    BEHAVIOUR_START { }
    BEHAVIOUR_END { }

protected:

    virtual bool OnSetFire() = 0;

};

class BIOnLight : public BI< Creature*, Behaved* > {
public:

    BEHAVIOUR_CALL
    {
        return OnLight( a0, a1 );
    }

    BEHAVIOUR_START { }
    BEHAVIOUR_END { }

protected:

    virtual bool OnLight( Creature* c, Behaved* target ) = 0;

};

#endif
